#include "EPSGLua/Exporter.h"

#include "EPSG/Cube.h"
#include "EPSG/Leaf.h"
#include "EPSG/Mesh.h"
#include "EPSG/Node.h"
#include "EPSG/Scene.h"
#include "EPSG/Shape.h"
#include "EPSG/Group.h"
#include "EPSG/Camera.h"
#include "EPSG/Engine.h"
#include "EPSG/Entity.h"
#include "EPSG/Sphere.h"
#include "EPSG/Switch.h"
#include "EPSG/Environ.h"
#include "EPSG/Texture.h"
#include "EPSG/Material.h"
#include "EPSG/Billboard.h"
#include "EPSG/Transform.h"
#include "EPSG/Appearance.h"
// Lights
#include "EPSG/LightSource.h"
#include "EPSG/Manipulator.h"
#include "EPSG/OmniLight.h"
#include "EPSG/SpotLight.h"
#include "EPSG/DirectionalLight.h"
// Manipulators
#include "EPSG/LookManipulator.h"
#include "EPSG/WalkManipulator.h"
#include "EPSG/MouseManipulator.h"

#include "EPSGLua/Global.h"
#include "EPSGLua/LuaEngine.h"
#include "EPSGLua/LuaFunctions.h"

#include <stdio.h>

using namespace luabind;
using namespace EPSG;
using namespace EPSGLua;

bool EPSGLua::Exporter::s_prepared = false;

void EPSGLua::Exporter::prepareLua()
{
	module( Global::instance()->getLuaState() )
	[
		//// Export Node to Lua
		class_<Node>( "Node" )
			.def( "setName", &Node::setName )
			.def( "print", &Node::print )
		,

		//// Export Group to Lua
		class_<Group, Node>( "Group" )
			.def( constructor<>() )
			.def( "addChild", &Group::addChild )
		,

		//// Export Scene to Lua
		class_<Scene, Group>( "Scene" )
			.def( constructor<>() )
			.def( "addChild", &Scene::addChild )
			.def( "setBackColor", &Scene::setBackColor )
			.def( "setEnviron", &Scene::setEnviron )
			.def( "setBackfaceCulling", &Scene::setBackfaceCulling )
		,

		//// Export Transform to Lua
		class_<Transform, Group>( "Transform" )
			.def( constructor<>() )
			.def( "addChild", &Transform::addChild )
			.def( "translate", &Transform::translate )
			.def( "rotate", (void(Transform::*)(float, float, float)) &Transform::rotate )
			.def( "rotate", (void(Transform::*)(float, float, float, float)) &Transform::rotate )
			.def( "scale", &Transform::scale )
		,

		//// Export Switch to Lua
		class_<Switch, Group>( "Switch" )
			.def( constructor<>() )
			.def( "addChild", &Switch::addChild )
			.def( "setActive", (void(Switch::*)(int)) &Switch::setActive )
			.def( "setActive", (void(Switch::*)(EPSG::Node*)) &Switch::setActive )
		,

		//// Export Leaf to Lua
		class_<Leaf, Node>( "Leaf" )
		,

		//// Export Camera to Lua
		class_<Camera, Leaf>( "Camera" )
			.def( constructor<>() )
			.def( "setActive", &Camera::setActive )
			.def( "setFovY", &Camera::setFovY )
			.def( "setZPlanes", &Camera::setZPlanes )
			.def( "setEye", (void(Camera::*)(float, float, float)) &Camera::setEye )
			.def( "setEye", (void(Camera::*)(Vec3<float>)) &Camera::setEye )
			.def( "setCenter", (void(Camera::*)(float, float, float)) &Camera::setCenter )
			.def( "setCenter", (void(Camera::*)(Vec3<float>)) &Camera::setCenter )
			.def( "setUp", (void(Camera::*)(float, float, float)) &Camera::setUp )
			.def( "setUp", (void(Camera::*)(Vec3<float>)) &Camera::setUp )
			.def( "setParent", &Camera::setParent )
			.def( "translate", &Camera::translate )
			.def( "rotate", (void(Camera::*)(float, float, float)) &Camera::rotate )
			.def( "rotate", (void(Camera::*)(float, float, float, float)) &Camera::rotate )
		,

		//// Export Entity to Lua
		class_<Entity, Leaf>( "Entity" )
			.def( constructor<>() )
			.def( constructor<Appearance*, Shape*>() )
			.def( "setAppearance", &Entity::setAppearance )
			.def( "setShape", &Entity::setShape )
			.def( "setPolygonOffset", &Entity::setPolygonOffset )
			.def( "setToonShading", &Entity::setToonShading )
			.def( "setToonBorderWidth", &Entity::setToonBorderWidth )
			.def( "setToonBorderColor", &Entity::setToonBorderColor )
		,

		//// Export Entity to Lua
		class_<Billboard, Leaf>( "Billboard" )
			.def( constructor<>() )
			.def( constructor<Appearance*, float, float>() )
			.def( "setAppearance", &Billboard::setAppearance )
			.def( "setPolygonOffset", &Billboard::setPolygonOffset )
			.def( "setDimensions", &Billboard::setDimensions )
		,

		//// Export LightSource to Lua
		class_<LightSource, Leaf>( "LightSource" )
			.def( constructor<>() )
			.def( "setAmbient", &LightSource::setAmbient )
			.def( "setDiffuse", &LightSource::setDiffuse )
			.def( "setSpecular", &LightSource::setSpecular )
			.def( "enable", &LightSource::enable )
		,

		//// Export DirectionalLight to Lua
		class_<DirectionalLight, LightSource>( "DirectionalLight" )
			.def( constructor<>() )
			.def( "setDirection", &DirectionalLight::setDirection )
		,

		//// Export OmniLight to Lua
		class_<OmniLight, LightSource>( "OmniLight" )
			.def( constructor<>() )
			.def( "setPosition", &OmniLight::setPosition )
		,

		//// Export SpotLight to Lua
		class_<SpotLight, LightSource>( "SpotLight" )
			.def( constructor<>() )
			.def( "setPosition", &SpotLight::setPosition )
			.def( "setDirection", &SpotLight::setDirection )
			.def( "setCutoff", &SpotLight::setCutoff )
			.def( "setExponent", &SpotLight::setExponent )
		,

		//// Export Shape to Lua
		class_<Shape>( "Shape" )
		,

		//// Export Cube to Lua
		class_<Cube, Shape>( "Cube" )
			.def( constructor<>() )
			.def( constructor<float, float, float>() )
			.def( "setDimensions", &Cube::setDimensions )
			.def( "setSegments", &Cube::setSegments )
		,

		//// Export Mesh to Lua
		class_<Mesh, Shape>( "Mesh" )
			.def( constructor<>() )
			.def( constructor<const char*>() )
			.def( "loadGeometry", &Mesh::loadGeometry )
			.def( "setSmooth", &Mesh::setSmooth )
		,

		//// Export Sphere to Lua
		class_<Sphere, Shape>( "Sphere" )
			.def( constructor<>() )
			.def( "setRadius", &Sphere::setRadius )
			.def( "setSlices", &Sphere::setSlices )
			.def( "setStacks", &Sphere::setStacks )
		,

		//// Export Appearance to Lua
		class_<Appearance>( "Appearance" )
		,

		//// Export Texture to Lua
		class_<Texture, Appearance>( "Texture" )
			.def( constructor<>() )
			.def( constructor<const char*>() )
			.def( "loadFile", &Texture::loadFile )
			.def( "setProjective", &Texture::setProjective )
			.def( "setPlaneS", &Texture::setPlaneS )
			.def( "setPlaneT", &Texture::setPlaneT )
		,

		//// Export Material to Lua
		class_<Material, Appearance>( "Material" )
			.def( constructor<>() )
			.def( "setAmbient", &Material::setAmbient )
			.def( "setDiffuse", &Material::setDiffuse )
			.def( "setSpecular", &Material::setSpecular )
			.def( "setShininess", &Material::setShininess )
			.def( "whiteMaterial", &Material::whiteMaterial )
		,

		//// Export Engine to Lua
		class_<Engine>( "Engine" )
		,

		//// Export Manipulator to Lua
		class_<Manipulator, Engine>( "Manipulator" )
		,

		//// Export LookManipulator to Lua
		class_<LookManipulator, Manipulator>( "LookManipulator" )
			.def( constructor<Camera*>() )
		,

		//// Export WalkManipulator to Lua
		class_<WalkManipulator, Manipulator>( "WalkManipulator" )
			.def( constructor<Camera*>() )
		,

		//// Export MouseManipulator to Lua
		class_<MouseManipulator, Manipulator>( "MouseManipulator" )
			.def( constructor<Camera*>() )
		,

		//// Export LuaEngine to Lua
		class_<LuaEngine, Engine>( "LuaEngine" )
			.def( constructor<>() )
			.def( "apply", &LuaEngine::apply )
			.def( "registerKey", &LuaEngine::registerKey )
		,

		//// Export Environ to Lua
		class_<Environ>( "Environ" )
			.def( constructor<>() )
			.def( "setFogMode", &Environ::setFogMode )
			.def( "setFogColor", &Environ::setFogColor )
			.def( "setFogDensity", &Environ::setFogDensity )
			.def( "setFogHint", &Environ::setFogHint )
			.def( "setFogStart", &Environ::setFogStart )
			.def( "setFogEnd", &Environ::setFogEnd )
		,

		def( "updateView", &EPSGLua::LuaFunctions::updateView ),
		def( "wait", &EPSGLua::LuaFunctions::wait )
	];

	EPSGLua::LuaFunctions::initialize();

	s_prepared = true;
}

bool EPSGLua::Exporter::isPrepared()
{
	return s_prepared;
}